package uml2Java;

import java.util.Map;

import org.eclipse.emf.common.util.EList;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.Class;

import astjava.ClassDeclaration;
import astjava.InterfaceDeclaration;
import astjava.JavaFactory;
import astjava.TypeAccess;


public class TransformInheritance {

	private Package _umlPackage; 
	
	private Map<String, astjava.Type> _symbolMap;
	
	public TransformInheritance(TransformPackagesAndTypes transformerTypes) {
		_umlPackage = transformerTypes.get_umlPackage();
		_symbolMap = transformerTypes.get_symbolMap();
	}
	
	public void doTransformInheritance() throws MultipleInheritanceNotAllowedException {
		EList<Type> umlTypes = _umlPackage.getOwnedTypes();
		for (Type umlType : umlTypes) {
			if (umlType instanceof Interface) {
				InterfaceDeclaration javaInterface = (InterfaceDeclaration) _symbolMap.get(umlType.getName());
				Interface umlInterface = (Interface) umlType;
				for (Generalization generalization :  umlInterface.getGeneralizations()) {
					if (generalization.getGeneral() instanceof Interface) {
						javaInterface.getSuperInterfaces().add(transformSuperType(generalization.getGeneral()));
					}
				}
			}
			if (umlType instanceof Class) {
				ClassDeclaration javaClass = (ClassDeclaration) _symbolMap.get(umlType.getName());
				Class umlClass = (Class) umlType;
				boolean hasSuperClass = false;
				for (Generalization generalization :  umlClass.getGeneralizations()) {
					if (generalization.getGeneral() instanceof Interface) {
						javaClass.getSuperInterfaces().add(transformSuperType(generalization.getGeneral()));
					}
					else if (generalization.getGeneral() instanceof Class && !hasSuperClass) {
						javaClass.setSuperClass(transformSuperType(generalization.getGeneral()));
						hasSuperClass = true;
					}
					else throw new MultipleInheritanceNotAllowedException(umlClass);
				}
			}
		}
	}

	private TypeAccess transformSuperType(Classifier superType) {
		TypeAccess javaSuperType = JavaFactory.eINSTANCE.createTypeAccess();
		javaSuperType.setType(_symbolMap.get(superType.getName()));
		return javaSuperType;
	}
}
